<!DOCTYPE html>
<html>
  <head>
    <title>threejs</title>
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=2,maximum-scale=1,user-scalable=yes" />
    <metahttp-equiv ="X-UA-Compatible" content="IE=edge,chrome=1" />

    <style>
      html,
      body {
        padding: 0;
        margin: 0;
        overflow: hidden;
      }

      canvas {
        width: 100%;
        height: 100%;
      }
    </style>
  </head>

  <body>
    <script type="module">
      import * as THREE from "https://cdn.skypack.dev/three@v0.129.0";
      import { OrbitControls } from "https://cdn.skypack.dev/three@v0.129.0/examples/jsm/controls/OrbitControls.js";

      // 创建渲染器
      var renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight); // 设置canvas画布大小
      renderer.setPixelRatio(window.devicePixelRatio);
      document.body.appendChild(renderer.domElement); // canvas画布插入dom树

      // 创建场景
      var scene = new THREE.Scene();
      scene.background = new THREE.Color("#347897");

      // 辅助线
      var axisHelper = new THREE.AxisHelper(500);
      scene.add(axisHelper);

      // 添加点光源
      let light1 = new THREE.PointLight("#fff", 0.8);
      light1.position.set(2160, 1160, 0);
      scene.add(light1);

      //环境光
      let ambient = new THREE.AmbientLight("#fff", 0.5);
      scene.add(ambient);

      // 创建相机
      var camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 10000);
      camera.position.set(0, 550, 870); // 设置相机位置

      // 创建控制器
      let controls = new OrbitControls(camera, renderer.domElement);
      //controls.autoRotate = true

      // 渲染
      !(function render() {
        controls.update(); // Update controls
        renderer.render(scene, camera);
        requestAnimationFrame(render);
      })();

      // 创建火焰
      for (let i = 0; i < 300; i++) {
        const position = [Math.random() * 1000 - 500, 100, Math.random() * 1000 - 500]; // 位置
        const size = 320; // 大小
        const circle = 1.5; // 周期，单位秒
        const opacity = 0.1; // 透明度
        const textureUrl = "http://182.43.179.137:81/public/images/texture-fire.png";
        const frameNum = 15; // 帧数
        let currFrame = 1;
        let frameId = null;

        // 几何体
        const geometry = new THREE.BufferGeometry();
        const posArr = [0, 0, 0];
        geometry.setAttribute("position", new THREE.BufferAttribute(new Float32Array(posArr), 3));

        // 纹理和材质
        const texture = new THREE.TextureLoader().load(textureUrl);
        const material = new THREE.PointsMaterial({
          map: texture,
          transparent: true,
          depthWrite: false,
          opacity: opacity,
          size: size, // 图元大小
          sizeAttenuation: true, // 大小是否随相机深度衰减
          blending: THREE.AdditiveBlending,
        });

        // 物体
        const obj = new THREE.Points(geometry, material);
        const [x, y, z] = position;
        // this.obj.position.set(x, y + this.size / 2, z); // 设置位置
        obj.position.set(x, y, z); // 设置位置

        // 调整纹理
        texture.repeat.set(1 / frameNum, 1);
        texture.offset = new THREE.Vector2((currFrame - 1) / frameNum, 0);
        scene.add(obj);

        // 燃烧动画
        function start() {
          if (frameId) return;
          const startFrame = currFrame; // 起始帧
          const st = Date.now();
          // 请求动画帧
          const h = () => {
            frameId = requestAnimationFrame(h);
            const dt = (Date.now() - st) / 1000;
            currFrame = startFrame + Math.floor(dt / (circle / frameNum)); // 当前帧计算
            currFrame = currFrame % frameNum; // 修正
            if (currFrame == 0) currFrame = frameNum; // 修正
            texture.offset = new THREE.Vector2((currFrame - 1) / frameNum, 0);
          };
          frameId = requestAnimationFrame(h);
        }

        start(); // 燃烧
      }

      // 创建一个地面作参考
      const texture1 = new THREE.TextureLoader().load("http://182.43.179.137:81/public/images/texture-wood2.jpg"); // 立方纹理加载器
      texture1.wrapS = THREE.RepeatWrapping;
      texture1.wrapT = THREE.RepeatWrapping;
      texture1.repeat.set(10, 10);
      var geometry1 = new THREE.PlaneGeometry(3000, 3000); // 平面几何体
      var material1 = new THREE.MeshPhongMaterial({ map: texture1, side: THREE.DoubleSide });
      var plane = new THREE.Mesh(geometry1, material1); // 创建模型
      plane.rotateX((Math.PI / 180) * 90);
      scene.add(plane); // 加入场景

      // 创建一个箱子
      const g = new THREE.BoxGeometry(150, 150, 150);
      const m = new THREE.MeshStandardMaterial({ color: "#ff00ff" });
      //scene.add(new THREE.Mesh(g, m));
    </script>
  </body>
</html>
